package cn.sciento.export;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import cn.sciento.core.redis.RedisHelper;
import cn.sciento.export.config.ExportInitializeConfig;
import cn.sciento.export.endpoint.AsyncExportEndpoint;
import cn.sciento.export.filler.MultiSheetFiller;
import cn.sciento.export.filler.SingleSheetFiller;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableConfigurationProperties({ExportProperties.class})
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class ExportAutoConfiguration {
    @Bean
    public ExportColumnHelper exportColumnHelper(ExportProperties properties, RedisHelper redisHelper) {
        return new ExportColumnHelper(properties, redisHelper);
    }

    @Bean
    @ConditionalOnProperty(value = {"stong.export.enable-async"}, havingValue = "true")
    public ExportFutureManager futureManager() {
        return new ExportFutureManager();
    }

    @Bean
    @ConditionalOnProperty(value = {"stong.export.enable-async"}, havingValue = "true")
    public AsyncExportEndpoint asyncExportEndpoint() {
        return new AsyncExportEndpoint();
    }

    @Bean
    @ConditionalOnProperty(value = {"stong.export.enable-async"}, havingValue = "true")
    public ExportDataHelper asyncExportDataHelper(ExportProperties properties, ExportFutureManager futureManager, ExportColumnHelper exportColumnHelper) {
        ExecutorService executorService = new ThreadPoolExecutor(properties.getCorePoolSize().intValue(), properties.getMaximumPoolSize().intValue(), properties.getKeepAliveTime().toMillis(), TimeUnit.MILLISECONDS, (properties.getQueueSize() == null) ? new LinkedBlockingQueue<>() : new LinkedBlockingQueue<>(properties.getQueueSize().intValue()), r -> new Thread(r, properties.getAsyncThreadName()));
        return new ExportDataHelper(exportColumnHelper, executorService, futureManager);
    }

    @Bean
    @ConditionalOnMissingBean
    public ExportDataHelper exportDataHelper(ExportColumnHelper exportColumnHelper) {
        return new ExportDataHelper(exportColumnHelper);
    }

    @Bean
    public ExcelExportAop excelExportAop(ExportDataHelper exportDataHelper, ExportColumnHelper exportColumnHelper) {
        return new ExcelExportAop(exportDataHelper, exportColumnHelper);
    }

    @Bean
    public ExportInitializeConfig exportInitializeConfig() {
        return new ExportInitializeConfig();
    }

    @Bean
    public MultiSheetFiller multiSheetFiller() {
        return new MultiSheetFiller();
    }

    @Bean
    public SingleSheetFiller singleSheetFiller() {
        return new SingleSheetFiller();
    }

    @Bean(initMethod = "init")
    public ExcelFillerHolder excelFillerHolder() {
        return new ExcelFillerHolder();
    }
}
